package de.barny.gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.LinkedList;
import java.util.List;

import javax.swing.JPanel;
import javax.swing.Timer;

import de.barny.obj.Apple;
import de.barny.obj.Dot;
import de.barny.obj.Snake;
import de.barny.prefs.ResourceBundleHelper;

public class GameField extends JPanel implements ActionListener {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	Timer timer;

	Color gameFieldColor = new Color(0, 0, 0);

	public static List<Apple> apple = new LinkedList<Apple>();

	public static List<Snake> snakes = new LinkedList<Snake>();

	int initdots = Integer.parseInt(getResource("snake.dot.start.value"));
	int delay = Integer.parseInt(getResource("snake.speed"));

	public static boolean collided;
	boolean paintApple = true;

	boolean pause = false;

	GameField() {
		setLayout(new BorderLayout());
		setBackground(gameFieldColor);
		setFocusable(true);
		addKeyListener(keyListener);
		initGame();
	}

	@Override
	protected void paintComponent(Graphics gameFieldGraphics) {
		super.paintComponent(gameFieldGraphics);

		Graphics2D gField = (Graphics2D)gameFieldGraphics;
		gField.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

		for (Snake snake: snakes) {
			snake.paint(gameFieldGraphics);
		}

		checkCollision();

		if (snakes.size() != 0) {
			int score1 = snakes.get(0).getDots().size() - Integer.parseInt(getResource("snake.dot.start.value"));
			int score2 = snakes.get(1).getDots().size() - Integer.parseInt(getResource("snake.dot.start.value"));
			Double exRising = Double.parseDouble(getResource("score.exponential.rising"));
			String currentScore1 = "1. Spieler: " + Math.round((score1*Math.pow(exRising, score1)));
			String currentScore2 = "2. Spieler: " + Math.round((score2*Math.pow(exRising, score2)));

			gField.setColor(new Color(255, 0, 0, 200));
			gField.setFont(new Font("Calibri", Font.PLAIN, 40));
			gField.drawString(currentScore1, 25 , 50);
			gField.setColor(new Color(0, 255, 0, 200));
			gField.drawString(currentScore2, Integer.parseInt(getResource("window.size.width")) - (25 + 15*currentScore2.length()) , 50);
		}

		if (paintApple && apple.size() != 0) {
			apple.get(0).paint(gameFieldGraphics);
		}
	}

	public void addSnakes(int player) {
		for (int i = 1; i <= player; i++) {
			snakes.add(new Snake(Integer.parseInt(getResource("snake.dot.start.value")), i));
		}
	}

	public void initGame() {
		addSnakes(Integer.parseInt(getResource("player.number")));
		apple.add(new Apple());
		apple.get(0).setRandomPos();
		timer = new Timer(delay, this);
		timer.start();
	}

	public void restart() {
		collided = false;
		pause = false;
		for (Snake snake: snakes) {
			snake.initSnake(Integer.parseInt(getResource("snake.dot.start.value")));
		}
		setApple();
	}

	public static void setApple() {
		apple.get(0).setRandomPos();
	}

	public void checkCollision() {
		for (Dot dot: snakes.get(1).dots) {
			if (snakes.get(0).getLastDot().getPosX() == dot.getPosX() && snakes.get(0).getLastDot().getPosY() == dot.getPosY()) {
				collided = true;
			}
		}
		
		for (Dot dot: snakes.get(0).dots) {
			if (snakes.get(1).getLastDot().getPosX() == dot.getPosX() && snakes.get(1).getLastDot().getPosY() == dot.getPosY()) {
				collided = true;
			}
		}

		for (Snake snake: snakes) {

			for (Dot dot: snake.dots) {
				if (snake.getLastDot().getPosX() == dot.getPosX() && snake.getLastDot().getPosY() == dot.getPosY() && snake.getLastDot() != dot) {
					collided = true;
				}
			}

			if (snake.getLastDot().getPosX() <= 0 || snake.getLastDot().getPosY() <= 0 || snake.getLastDot().getPosX() >= (Integer.parseInt(getResource("window.size.width"))/Integer.parseInt(getResource("snake.dot.size"))) || snake.getLastDot().getPosY() >= (Integer.parseInt(getResource("window.size.height"))/Integer.parseInt(getResource("snake.dot.size")))) {
				collided = true;
			}

			if (snake.getLastDot().getPosX() == GameField.apple.get(0).getPosX() && snake.getLastDot().getPosY() == GameField.apple.get(0).getPosY()) {
				snake.addDot();
				setApple();
			}
		}
	}

	private String getResource(String a_strResourceKey) {
		return ResourceBundleHelper.getResource(a_strResourceKey);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		if (!pause && !collided) {
			repaint();
		}
	}

	KeyListener keyListener = new KeyListener() {

		@Override
		public void keyPressed(KeyEvent e) {
			int key = e.getKeyCode();

			if (!pause) {
				if (key == KeyEvent.VK_A) {
					snakes.get(1).setDirection('l');
				} else if (key == KeyEvent.VK_D) {
					snakes.get(1).setDirection('r');
				} else if (key == KeyEvent.VK_W) {
					snakes.get(1).setDirection('u');
				} else if (key == KeyEvent.VK_S) {
					snakes.get(1).setDirection('d');
				}

				if (key == KeyEvent.VK_LEFT) {
					snakes.get(0).setDirection('l');
				} else if (key == KeyEvent.VK_RIGHT) {
					snakes.get(0).setDirection('r');
				} else if (key == KeyEvent.VK_UP) {
					snakes.get(0).setDirection('u');
				} else if (key == KeyEvent.VK_DOWN) {
					snakes.get(0).setDirection('d');
				}
			}

			if (key == KeyEvent.VK_ESCAPE) {
				if (!pause) {
					pause = true;
				} else {
					pause = false;
				}
			}

			if (key == KeyEvent.VK_R) {
				restart();
			}
		}

		@Override
		public void keyReleased(KeyEvent arg0) {
			// TODO Auto-generated method stub

		}

		@Override
		public void keyTyped(KeyEvent arg0) {
			// TODO Auto-generated method stub

		}
	};

}
